/*
 * Copyright (c) 2025 Huawei Technologies Co., Ltd.
 * openUBMC is licensed under Mulan PSL v2.
 * You can use this software according to the terms and conditions of the Mulan PSL v2.
 * You may obtain a copy of Mulan PSL v2 at:
 *         http://license.coscl.org.cn/MulanPSL2
 * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
 * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
 * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
 * See the Mulan PSL v2 for more details.
 */

#ifndef MCPY_BUILTINS_ANY_VALUE_H
#define MCPY_BUILTINS_ANY_VALUE_H

#include <algorithm>
#include <cstddef>
#include <cstring>
#include <new>
#include <type_traits>
#include <utility>

namespace mcpy {

// 类型擦除的值容器（类似 union，但支持任意类型）
// 使用固定大小的 buffer + placement new 实现零开销类型擦除
template <size_t BufferSize = 128, size_t Alignment = alignof(std::max_align_t)>
class any_value {
public:
    any_value() = default;

    any_value(const any_value& other) noexcept {
        std::memcpy(m_buffer, other.m_buffer, BufferSize);
        m_exception  = other.m_exception;
        m_destructor = other.m_destructor;
    }

    any_value& operator=(const any_value& other) noexcept {
        if (this != &other) {
            destroy();
            std::memcpy(m_buffer, other.m_buffer, BufferSize);
            m_exception  = other.m_exception;
            m_destructor = other.m_destructor;
        }
        return *this;
    }

    any_value(any_value&& other) noexcept {
        std::memcpy(m_buffer, other.m_buffer, BufferSize);
        m_exception        = other.m_exception;
        m_destructor       = other.m_destructor;
        other.m_exception  = nullptr;
        other.m_destructor = nullptr;
    }

    any_value& operator=(any_value&& other) noexcept {
        if (this != &other) {
            destroy();
            std::memcpy(m_buffer, other.m_buffer, BufferSize);
            m_exception        = other.m_exception;
            m_destructor       = other.m_destructor;
            other.m_destructor = nullptr;
            other.m_exception  = nullptr;
        }
        return *this;
    }

    ~any_value() {
        destroy();
    }

    template <typename T>
    void emplace(T&& value) noexcept {
        using DecayT = std::decay_t<T>;
        static_assert(sizeof(DecayT) <= BufferSize,
                      "await 返回值类型过大，请增加 BufferSize");
        static_assert(alignof(DecayT) <= Alignment,
                      "await 返回值类型对齐要求过高");

        if (m_destructor && m_destructor != &noop_destructor) {
            m_destructor(m_buffer);
            m_destructor = nullptr;
        }

        new (m_buffer) DecayT(std::forward<T>(value));

        if constexpr (!std::is_trivially_destructible_v<DecayT>) {
            m_destructor = &destruct_impl<DecayT>;
        } else {
            m_destructor = &noop_destructor;
        }
    }

    template <typename T>
    T& get() {
        if (m_exception) {
            std::rethrow_exception(m_exception);
        }
        return *reinterpret_cast<T*>(m_buffer);
    }

    template <typename T>
    const T& get() const {
        if (m_exception) {
            std::rethrow_exception(m_exception);
        }
        return *reinterpret_cast<const T*>(m_buffer);
    }

    bool empty() const noexcept {
        return m_destructor == nullptr;
    }

    void set_exception(std::exception_ptr e) noexcept {
        m_exception = e;
    }

    bool has_exception() const noexcept {
        return m_exception != nullptr;
    }

    std::exception_ptr get_exception() const noexcept {
        return m_exception;
    }

private:
    alignas(Alignment) char m_buffer[BufferSize]{};
    std::exception_ptr m_exception = nullptr;
    void (*m_destructor)(void*)    = nullptr;

    // 空析构（用于平凡类型的 sentinel）
    static void noop_destructor(void*) {
    }

    // 析构实现
    template <typename T>
    static void destruct_impl(void* ptr) {
        if constexpr (!std::is_trivially_destructible_v<T>) {
            static_cast<T*>(ptr)->~T();
        }
    }

    void destroy() {
        if (m_destructor && m_destructor != &noop_destructor) {
            m_destructor(m_buffer);
        }
        m_destructor = nullptr;
        m_exception  = nullptr;
    }
};

// 类型别名：不同大小的 any_value
using any_value_small  = any_value<32>;  // 小对象优化（32字节）
using any_value_medium = any_value<64>;  // 中等对象（64字节）
using any_value_large  = any_value<256>; // 大对象（256字节）

// 元模板：根据类型列表自动选择合适大小的 any_value
namespace detail {
template <typename... Types>
struct max_sizeof {
    static constexpr size_t value = std::max({sizeof(Types)...});
};

template <>
struct max_sizeof<> {
    static constexpr size_t value = 0;
};

template <typename... Types>
struct max_alignof {
    static constexpr size_t value = std::max({alignof(Types)...});
};

template <>
struct max_alignof<> {
    static constexpr size_t value = alignof(std::max_align_t);
};
} // namespace detail

// 自动选择合适大小的 any_value 类型
template <typename... Types>
struct any_value_for {
private:
    static constexpr size_t max_size  = detail::max_sizeof<Types...>::value;
    static constexpr size_t max_align = detail::max_alignof<Types...>::value;

    // 根据最大 size 选择合适的 buffer 大小
    static constexpr size_t buffer_size = max_size == 0     ? 128
                                          : max_size <= 32  ? 32
                                          : max_size <= 64  ? 64
                                          : max_size <= 128 ? 128
                                                            : 256;

public:
    using type = any_value<buffer_size, max_align>;
};

// 便捷别名
template <typename... Types>
using any_value_for_t = typename any_value_for<Types...>::type;

} // namespace mcpy

#endif // MCPY_BUILTINS_ANY_VALUE_H
